package com.zzjc.web.util;


import com.alibaba.druid.util.StringUtils;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件、图片上传、下载封装工具类
 */
public class UploadFileUtil {
	public final static Logger logger = LoggerFactory.getLogger(UploadFileUtil.class);

	//图片后缀格式类型
	private static String imgExtType = "bmp,BMP,jpg,JPG,jpeg,JPEG,png,PNG";

	//文件、图片上传地址(默认)
	private static String fileUrlDefult = "/mnt/qlfzFileServer/";

	/**
	 * 文件、图片上传<br>
	 *     返回服务器中文件名
	 */
	public static Map<String, String> upload(byte[] file_buff, String fileExt){
		String fileUrlStr = "";  //服务器路径
		String sysFileName = ""; //文件名
		String sysFilePath = ""; //文件路径
		Map<String,String> resultMap = new HashMap<>();

		try {
			//1.若为图片格式文件则调用压缩方法，最小压缩为800Kb
			if (fileExt.indexOf(imgExtType) >= 0) {
				long maxScaleSize = 800;
				byte[] fileBuffScale = compressPicForScale(file_buff, maxScaleSize);
				if (fileBuffScale.length > 0) {
					file_buff = fileBuffScale;
				}
			}

			//2.生成文件路径、文件名
			fileUrlStr = getFileUrl();
			sysFileName = getFileName(fileExt);
			sysFilePath = fileUrlStr + "/" + sysFileName;


			//3.文件流上传至服务器
			File tempFile = new File(sysFilePath);
			FileOutputStream outStream = new FileOutputStream(tempFile); //创建输出流
			outStream.write(file_buff);//写入数据
			outStream.close();//关闭输出流
			resultMap.put("fileName",sysFileName);
			resultMap.put("localPath",fileUrlStr);
			resultMap.put("fileExt",fileExt);


		}catch (Exception e){
			logger.info("文件、图片上传异常");
			e.printStackTrace();
		}


		return resultMap;
	}

	/**
	 * 创建文件路径<br>
	 *     服务器目录 + 当前日期
	 * @return
	 */
	public static String getFileUrl() {
		return getFileUrl(null);
	}
	public static String getFileUrl(String pointPath) {
		//1.获取服务器存储路径，tomcat上一级路径
		String rootDirectoryPath = System.getProperty("catalina.home"); //获取到的是tomcat的根路径
		String parentParent = new File(rootDirectoryPath).getParent();

		//2.判断文件路径是否存在
		String fileUrl = parentParent + "/qlfzFileServer/";
		if(StringUtils.isEmpty(fileUrl)){
			fileUrl = fileUrlDefult;
		}

		//3.判断目录节点是否为空，为空则获取当前月份生成目录节点
		if(StringUtils.isEmpty(pointPath)){
			pointPath= LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
		}

		//4.生成路径
		String fileUrlStr = fileUrl + pointPath;
		Boolean temp = new File(fileUrlStr).mkdirs();
		logger.info("----------上传的路径目录根为:::::" + fileUrlStr + "\t路径创建是否成功:::::" + temp);

		return fileUrlStr;
	}

	/**
	 * 创建文件名<br>
	 *     当前时间 + 4位随机数 + 文件后缀
	 * @param ext 文件后缀
	 * @return
	 */
	private static String getFileName(String ext) {
		String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
		String randomParam = String.valueOf((int)((Math.random()*9+1)*1000));
		return timeStr + "_" + randomParam + "." + ext;
	}

	/**
	 * 解析文件名<br>
	 * @param fileName 文件名
	 * @return map {prefix:前缀，ext:后缀}
	 */
	public static Map<String,String> resolveFileName(String fileName) {

		//1.解析文件名,获取文件前缀、文件后缀。文件命名统一采用当前时间 + 4位随机数 + 文件后缀。文件夹采用当前年月作为路径，所以截取6位
		String prefix = fileName.substring(0,6);
		String ext = fileName.substring(fileName.lastIndexOf("."),fileName.length());

		Map<String,String> retMap = new HashMap<>();
		retMap.put("prefix",prefix);
		retMap.put("ext",ext);
		return retMap;
	}


	/**
	 * 根据指定大小压缩图片
	 *
	 * @param imageBytes  源图片字节数组
	 * @param desFileSize 指定图片大小，单位kb
	 * @return 压缩质量后的图片字节数组
	 */
	public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
		if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
			return imageBytes;
		}
		long srcSize = imageBytes.length;
		double accuracy = getAccuracy(srcSize / 1024);
		try {
			while (imageBytes.length > desFileSize * 1024) {
				ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
				ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
				Thumbnails.of(inputStream).scale(accuracy).outputQuality(accuracy).toOutputStream(outputStream);
				imageBytes = outputStream.toByteArray();
			}
			logger.info("图片原大小={}kb | 压缩后大小={}kb", srcSize / 1024, imageBytes.length / 1024);
		} catch (Exception e) {
			logger.error("图片压缩失败!将原图上传服务器。--", e);
		}
		return imageBytes;
	}

	/**
	 * 自动调节精度(经验数值)
	 *
	 * @param size 源图片大小
	 * @return 图片压缩质量比
	 */
	private static double getAccuracy(long size) {
		double accuracy;

		if (size < 900) {
			accuracy = 0.95;
		} else if (size < 2047) {
			accuracy = 0.9;
		}  else {
			accuracy = 0.85;
		}
		return accuracy;
	}

	/*public static void main(String[] args) {
		String aaa =UploadFileUtil.createFileUrl(fileUrlDefult);
		System.out.println("aaaa::" + aaa);
	}*/
}
